package com.zzh.partnersys.common.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

/**
 * JWT 工具类
 * 用于生成和解析 JWT Token
 *
 * @author zzh
 */
@Slf4j
public class JwtUtil {

    /**
     * Token 有效期（毫秒）
     * 默认 10 小时：10 * 60 * 60 * 1000
     */
    public static final Long JWT_TTL = 10 * 60 * 60 * 1000L;

    /**
     * JWT 密钥（建议从配置文件读取，这里使用固定值）
     * 生产环境应该使用更复杂的密钥
     */
    private static final String JWT_KEY = "partner-system-jwt-secret-key-2024-zzh-partner-system-backend";

    /**
     * 生成密钥
     */
    private static SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(JWT_KEY.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 生成 UUID
     */
    private static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成 JWT Token
     *
     * @param userId 用户ID
     * @return JWT Token
     */
    public static String createToken(Long userId) {
        return createToken(userId, null);
    }

    /**
     * 生成 JWT Token
     *
     * @param userId    用户ID
     * @param ttlMillis Token 过期时间（毫秒），如果为 null 则使用默认值
     * @return JWT Token
     */
    public static String createToken(Long userId, Long ttlMillis) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        
        if (ttlMillis == null) {
            ttlMillis = JWT_TTL;
        }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);

        return Jwts.builder()
                .id(getUUID())                    // 唯一ID
                .subject(String.valueOf(userId))  // 主题：用户ID
                .issuer("partner-system")         // 签发者
                .issuedAt(now)                    // 签发时间
                .expiration(expDate)              // 过期时间
                .signWith(getSecretKey())         // 签名
                .compact();
    }

    /**
     * 解析 JWT Token
     *
     * @param token JWT Token
     * @return Claims 对象
     * @throws Exception 解析失败时抛出异常
     */
    public static Claims parseToken(String token) throws Exception {
        return Jwts.parser()
                .verifyWith(getSecretKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    /**
     * 从 Token 中获取用户ID
     *
     * @param token JWT Token
     * @return 用户ID，如果解析失败返回 null
     */
    public static Long getUserIdFromToken(String token) {
        try {
            Claims claims = parseToken(token);
            String subject = claims.getSubject();
            return Long.parseLong(subject);
        } catch (Exception e) {
            log.error("从 Token 中获取用户ID失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 验证 Token 是否有效
     *
     * @param token JWT Token
     * @return true 表示有效，false 表示无效
     */
    public static boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            // 检查是否过期
            return claims.getExpiration().after(new Date());
        } catch (Exception e) {
            log.debug("Token 验证失败: {}", e.getMessage());
            return false;
        }
    }
}

